﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using System.Linq;
using OfficeOpenXml;

namespace ToolExcelPub
{
    public static partial class XTool
    {
        public static void OutGo()
        {
            if (!OutputGoNeed) return;

            ShowInfo("OutGo!");

            OutGoEnum();

            OutGoStructPub();

            OutGoStruct();

            OutGoMap();
        }
        public static void OutGoEnum()
        {
            if (!OutputGoNeed) return;

            ShowInfo("OutGoEnum!");

            string pathServer = PathGo + "\\" + "conf-enum.go";

            var sbw = new StringBuilder();

            sbw.AppendLine($"package conf");

            Dictionary<string, Dictionary<string, string>> DictDictEnums = new Dictionary<string, Dictionary<string, string>>();
            Dictionary<string, string> DictDictEnumsDesc = new Dictionary<string, string>();
            foreach (var kvp in DictDictEnumPub)
            {
                DictDictEnums[kvp.Key] = kvp.Value;
                DictDictEnumsDesc[kvp.Key] = DictDictEnumPubDesc[kvp.Key];
            }
            foreach (var kvp in DictDictEnumPageId)
            {
                DictDictEnums[kvp.Key] = kvp.Value;
            }
            foreach (var kvp in DictDictEnumPage)
            {
                DictDictEnums[kvp.Key] = kvp.Value;
                DictDictEnumsDesc[kvp.Key] = DictDictEnumPubDesc[kvp.Key];
            }
            foreach (var kvp in DictDictEnums)
            {
                var eName = $"E{kvp.Key}";
                var sbnode = new StringBuilder();
                if (DictDictEnumsDesc.TryGetValue(kvp.Key, out var enumdesc))
                {
                    sbw.AppendLine($"// {eName} {enumdesc}");
                    sbw.AppendLine($"type {eName} int");
                    sbw.AppendLine();
                }
                else
                {
                    sbw.AppendLine($"// {eName} {eName}");
                    sbw.AppendLine($"type {eName} int");
                    sbw.AppendLine();
                }
                sbw.AppendLine($"const (");
                long min = 0, max = 0;
                foreach (var kvp2 in kvp.Value)
                {
                    sbnode.AppendLine($"\t{eName}{kvp2.Key} = {eName}({kvp2.Value})");
                    long.TryParse(kvp2.Value, out long tempmax);
                    min = Math.Min(min, tempmax);
                    max = Math.Max(max, tempmax);
                }
                sbw.Append(sbnode);
                sbw.AppendLine($")");
                sbw.AppendLine();
            }

            //服务器
            {
                ToolGlobal.WriteNewFile(pathServer, sbw.ToString());
            }
        }
        public static void OutGoStructPub()
        {
            if (!OutputGoNeed) return;

            ShowInfo("OutGoStruct!");

            string pathServer = PathGo + "\\" + "conf-structpub.go";

            var sbw = new StringBuilder();

            sbw.AppendLine($"package conf");
            sbw.AppendLine();

            foreach (var item in DictXPclassInfo.Values)
            {
                var sbnode = new StringBuilder();
                sbnode.AppendLine($"// {item.Desc}");
                sbnode.AppendLine($"type {item.Name} struct {{");
                foreach (var item2 in item.ListNode)
                {
                    sbnode.AppendLine($"\t// {item2[2]}");
                    sbnode.AppendLine($"\t{item2[1]} {GoGetTypeValue(item2[0])}");
                }
                sbnode.AppendLine($"}}");
                string stnode = sbnode.ToString();
                sbw.Append(stnode);
            }

            //服务器
            {
                ToolGlobal.WriteNewFile(pathServer, sbw.ToString());
            }
        }
        public static void OutGoStruct()
        {
            if (!OutputGoNeed) return;

            ShowInfo("OutGoStruct!");

            string pathServer = PathGo + "\\" + "conf-struct.go";

            var sbw = new StringBuilder();

            sbw.AppendLine($"package conf");
            sbw.AppendLine();

            foreach (var page in DictPages.Values)
            {
                if (!page.HasType(EToolFileType.服务器))
                {
                    continue;
                }
                var sbnode = new StringBuilder();
                sbnode.AppendLine($"// {page.NameFile}");
                sbnode.AppendLine($"type {page.Name} struct {{");
                for (int iii = 0; iii < page.Head.Count; iii++)
                {
                    if (page.Head[iii] == "")
                    {
                        continue;
                    }
                    string tp = page.TypeServer[iii];
                    if (string.IsNullOrEmpty(tp))
                    {
                        continue;
                    }
                    sbnode.AppendLine($"\t{page.Head[iii]} {GoGetTypeValue(tp)} \t// {page.HeadC[iii]}");
                }
                sbnode.AppendLine($"}}");
                sbw.Append(sbnode);
            }

            //服务器
            {
                ToolGlobal.WriteNewFile(pathServer, sbw.ToString());
            }
        }
        public static void OutGoMap()
        {
            string path_class = PathGo + "\\" + "conf-map.go";

            var sbw = new StringBuilder();

            sbw.AppendLine($"package conf");
            sbw.AppendLine();

            sbw.AppendLine($"import (");
            sbw.AppendLine($"\t\"fmt\"");
            sbw.AppendLine($"\t\"sync\"");
            sbw.AppendLine($")");

            sbw.AppendLine();
            sbw.AppendLine($"var (");
            sbw.AppendLine($"\tConfigLock sync.RWMutex //读写锁");
            foreach (var page in DictPages.Values)
            {
                if (!page.HasType(EToolFileType.服务器))
                {
                    continue;
                }
                var sbnode = new StringBuilder();
                var confname = page.Name.Replace("Config", "Map");
                var keytype = page.TypeClient[0];
                sbnode.AppendLine($"\t{confname} = make(map[{keytype}]{page.Name}) \t//{page.NameCn}\t// {page.NameFile}");
                sbw.Append(sbnode);
            }
            sbw.AppendLine($")");

            sbw.AppendLine();
            sbw.AppendLine($"func InitMapAll() bool {{");
            sbw.AppendLine($"\tfmt.Println(\"读取配置开始......\")");
            sbw.AppendLine();
            sbw.AppendLine($"\tConfigLock.Lock()");
            sbw.AppendLine($"\tdefer ConfigLock.Unlock()");
            sbw.AppendLine();

            foreach (var page in DictPages.Values)
            {
                if (!page.HasType(EToolFileType.服务器))
                {
                    continue;
                }
                var sbnode = new StringBuilder();
                var confname = page.Name.Replace("Config", "Map");
                sbnode.AppendLine($"\tif err := ReadJson(\"{page.Name}\", &{confname}); err != nil {{");
                sbnode.AppendLine($"\t\tfmt.Println(\"Read {page.Name} {page.NameCn} {page.NameFile} err\", err)");
                sbnode.AppendLine($"\t\treturn false");
                sbnode.AppendLine($"\t}}");
                sbw.Append(sbnode);
            }

            sbw.AppendLine();
            sbw.AppendLine($"\tfmt.Println(\"t读取配置结束......\")");
            sbw.AppendLine($"\treturn true");
            sbw.AppendLine($"}}");

            ToolGlobal.WriteNewFile(path_class, sbw.ToString());
        }
        public static string GoGetTypeValue(string tp)
        {
            string t = tp;
            switch (tp)
            {
                case "short": return "int16";
                case "long": return "int64";
                case "float": return "float32";
                case "double": return "float64";
                case "List<string>": return "[]string";
                case "List<int>": return "[]int";
                case "List<long>": return "[]int64";
                case "List<float>": return "[]float32";
                case "List<double>": return "[]float64";
                case "List<List<string>>": return "[][]string";
                case "List<List<int>>": return "[][]int";
                case "Dictionary<string,string>": return "map[string]string";
                case "Dictionary<int,int>": return "map[int]int";
                case "Dictionary<long,long>": return "map[int64]int64";
                case "Dictionary<string,int>": return "map[string]int";
                case "Dictionary<string, string>": return "map[string]string";
                case "Dictionary<int, int>": return "map[int]int";
                case "Dictionary<long, long>": return "map[int64]int64";
                case "Dictionary<string, int>": return "map[string]int";
                default:
                    {
                        var tpClient = tp;
                        if (DictXPclassInfo.ContainsKey(tpClient))
                        {
                        }
                        else
                        {
                            if (tpClient.StartsWith("List<"))
                            {
                                var pclassname = tpClient.GetMidStr("List<", ">");
                                if (DictXPclassInfo.ContainsKey(pclassname))
                                {
                                    t = $"[]{pclassname}";
                                }
                            }
                        }
                    }
                    break;
            }
            return t;
        }
        

    }
}
